use std::sync::Arc;
use tokio::fs::OpenOptions;
use tokio::io::AsyncWriteExt;
use std::io::Read;
use std::path::PathBuf;
use crate::download_manager::{DownloadTask, DownloadStatus};
use tauri::{AppHandle, Emitter};

// FTP下载实现
pub async fn download_ftp(app_handle: AppHandle, task: Arc<DownloadTask>) -> Result<String, String> {
    use std::str::FromStr;
    use url::Url;
    use suppaftp::FtpStream;

    // 解析URL
    let url = Url::parse(&task.url)
        .map_err(|e| format!("无效的URL: {}", e))?;
    
    let host = url.host_str().ok_or("缺少主机名")?;
    let port = url.port().unwrap_or(21);
    let path = url.path();
    let username = url.username();
    let password = url.password().unwrap_or("");

    // 连接FTP服务器
    let mut ftp_stream = FtpStream::connect(format!("{host}:{port}"))
        .map_err(|e| format!("连接FTP服务器失败: {}", e))?;

    // 登录
    ftp_stream.login(username, password)
        .map_err(|e| format!("FTP登录失败: {}", e))?;

    // 确保使用被动模式（通常默认启用）
    ftp_stream.transfer_type(suppaftp::types::FileType::Binary)
        .map_err(|e| format!("设置传输类型失败: {}", e))?;
    ftp_stream.custom_command("PASV", &[suppaftp::Status::PassiveMode])
        .map_err(|e| format!("设置被动模式失败: {}", e))?;

    // 获取文件大小
    let total_size = match ftp_stream.size(path) {
        Ok(size) => size,
        Err(e) => return Err(format!("获取文件大小失败: {}", e)),
    } as u64;

    // 更新总大小
    {
        let mut progress = task.progress.write().await;
        progress.total_size = total_size;
        progress.status = DownloadStatus::Downloading;
        let progress_clone = progress.clone();
        drop(progress);
        app_handle.emit("download_progress", progress_clone)
            .map_err(|e| e.to_string())?;
    }
    let file_path = format!("{}/{}", task.path, task.file_name);
    let mut local_file = OpenOptions::new()
        .create(true)
        .write(true)
        .open(&file_path)
        .await
        .map_err(|e| format!("创建本地文件失败: {}", e))?;
    let mut downloaded = 0u64;
    let app_handle = app_handle.clone();
    let task = task.clone();
    // 获取并读取文件内容
    ftp_stream.retr(path, |mut reader| {
        let mut buffer = vec![0; 8192];
        loop {
            match reader.read(&mut buffer) {
                Ok(n) if n == 0 => break,
                Ok(n) => {
                    if let Err(e) = std::fs::write(&file_path, &buffer[..n]) {
                        return Err(suppaftp::FtpError::ConnectionError(
                            std::io::Error::new(
                                std::io::ErrorKind::Other,
                                format!("写入文件失败: {}", e)
                            )
                        ));
                    }
                    downloaded += n as u64;
                }
                Err(e) => return Err(suppaftp::FtpError::ConnectionError(e)),
            }
        }
        Ok(())
    }).map_err(|e| format!("文件传输失败: {}", e))?;
    // 更新状态为完成
    let mut progress = task.progress.write().await;
    progress.status = DownloadStatus::Completed;
    let progress_clone = progress.clone();
    drop(progress);
    app_handle.emit("download_progress", progress_clone)
        .map_err(|e| e.to_string())?;

    Ok("下载完成".to_string())
}

// SFTP下载实现
pub async fn download_sftp(app_handle: AppHandle, task: Arc<DownloadTask>) -> Result<String, String> {
    use ssh2::Session;
    use std::net::TcpStream;
    use tokio::io::AsyncReadExt;
    use url::Url;

    // 解析URL获取主机名、路径等信息
    let url = Url::parse(&task.url)
        .map_err(|e| format!("无效的URL: {}", e))?;
    
    let host = url.host_str().ok_or("缺少主机名")?;
    let port = url.port().unwrap_or(22);
    let path = url.path();
    let username = url.username();
    let password = url.password().unwrap_or("");

    // 建立TCP连接
    let tcp = TcpStream::connect(format!("{host}:{port}"))
        .map_err(|e| format!("连接失败: {}", e))?;

    // 创建SSH会话
    let mut sess = Session::new()
        .map_err(|e| format!("创建SSH会话失败: {}", e))?;
    sess.set_tcp_stream(tcp);
    sess.handshake()
        .map_err(|e| format!("SSH握手失败: {}", e))?;

    // 身份验证
    sess.userauth_password(username, password)
        .map_err(|e| format!("认证失败: {}", e))?;

    // 创建SFTP会话
    let sftp = sess.sftp()
        .map_err(|e| format!("创建SFTP会话失败: {}", e))?;

    // 获取文件信息
    let remote_path = PathBuf::from(path);
    let stat = sftp.stat(&remote_path)
        .map_err(|e| format!("获取文件信息失败: {}", e))?;
    let total_size = stat.size.unwrap_or(0);

    // 更新总大小
    {
        let mut progress = task.progress.write().await;
        progress.total_size = total_size;
        progress.status = DownloadStatus::Downloading;
        let progress_clone = progress.clone();
        drop(progress);
        app_handle.emit("download_progress", progress_clone)
            .map_err(|e| e.to_string())?;
    }

    // 打开远程文件
    let mut remote_file = sftp.open(path)
        .map_err(|e| format!("打开远程文件失败: {}", e))?;

    // 创建本地文件
    let mut local_file = OpenOptions::new()
        .create(true)
        .write(true)
        .open(format!("{}/{}", task.path, task.file_name))
        .await
        .map_err(|e| format!("创建本地文件失败: {}", e))?;

    let mut buffer = vec![0; 8192];
    let mut downloaded = 0u64;

    // 读取数据并写入本地文件
    loop {
        // 检查是否取消下载
        if *task.cancel_flag.read().await {
            return Ok("下载已取消".to_string());
        }

        match remote_file.read(&mut buffer) {
            Ok(n) if n == 0 => break, // 文件读取完成
            Ok(n) => {
                local_file.write_all(&buffer[..n])
                    .await
                    .map_err(|e| format!("写入文件失败: {}", e))?;

                downloaded += n as u64;

                // 更新进度
                let mut progress = task.progress.write().await;
                progress.downloaded_size = downloaded;
                progress.progress = (downloaded as f64 / total_size as f64) * 100.0;
                let progress_clone = progress.clone();
                drop(progress);

                app_handle.emit("download_progress", progress_clone)
                    .map_err(|e| e.to_string())?;
            }
            Err(e) => return Err(format!("读取文件失败: {}", e)),
        }
    }

    // 更新状态为完成
    let mut progress = task.progress.write().await;
    progress.status = DownloadStatus::Completed;
    let progress_clone = progress.clone();
    drop(progress);
    app_handle.emit("download_progress", progress_clone)
        .map_err(|e| e.to_string())?;

    Ok("下载完成".to_string())
}